package com.example.glgk.service;

import com.example.glgk.dto.*;
import com.example.glgk.entity.DepartmentIndicatorEntity;
import com.example.glgk.entity.ElementDataEntity;
import com.example.glgk.entity.IndicatorDataEntity;
import com.example.glgk.mapper.*;
import com.example.glgk.utils.CalculatorUtils;
import com.example.glgk.utils.ExcelUtils;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lxk
 */
@Service
@Slf4j
public class EscalationDataService {

    private final static String DAY = "日";
    private final static String MONTH = "月";

    @Autowired
    IndicatorDataMapper indicatorDataMapper;

    @Autowired
    ElementDataDayMapper elementDataDayMapper;

    @Autowired
    ElementDataMonthMapper elementDataMonthMapper;

    @Autowired
    ElementDataMapper elementDataMapper;

    @Autowired
    DepCPMapper depCPMapper;

    /**
     * todo 考虑整个分页查询是否需要放到google的缓存中
     */
    public List<EscalationData> queryEscalationList(QueryEscalation queryEscalation) {
        PageHelper.startPage(queryEscalation.getPageNumber(), queryEscalation.getPageSize());
        return fasterQueryData(queryEscalation);
    }
    public void export(QueryEscalation queryEscalation, HttpServletResponse response) {
        List<EscalationData> escalationData = fasterQueryData(queryEscalation);
//        List<EscalationData> escalationData = queryData(queryEscalation);
        //需要对数据进行一下处理  不能展示原始数据，需要四舍五入，单位为 % 的需要乘以 100 拼接% 因为公式里面没有
        dataProcess(escalationData);
        // 导出 Excel todo 应该用范型的，图省事，后面有时间再改
        ExcelUtils.exportExcel(response, escalationData, EscalationData.class, queryEscalation);
    }

    /**
     * 处理导出数据
     *
     * @param escalationData
     */
    private void dataProcess(List<EscalationData> escalationData) {
        escalationData = escalationData.stream().filter(s -> StringUtils.isNotBlank(s.getUnit())).collect(Collectors.toList());
        for (EscalationData data : escalationData) {
            for (String key : data.getDynamicColumns().keySet()) {
                String value = data.getDynamicColumns().get(key);
                if (!"-".equals(data.getDynamicColumns().get(key))) {
                    if (data.getUnit().contains("%")) {
                        value = new BigDecimal(value).multiply(new BigDecimal(100)).setScale(4, RoundingMode.HALF_UP) + "%";
                    } else {
                        value = new BigDecimal(value).setScale(4, RoundingMode.HALF_UP) + "";
                    }
                    data.getDynamicColumns().put(key, value);
                }
            }
        }
    }

    /**
     * 查询速度更快 等逻辑全了再补
     * 有bug
     *
     * @param queryEscalation
     * @return
     */
    private List<EscalationData> fasterQueryData(QueryEscalation queryEscalation) {
        List<EscalationData> result = new ArrayList<>();
        //查询指标表中的所有的关于上报信息的元素定义公式 todo 后续查询where条件补充，只查询指标上报
        List<IndicatorDataEntity> list = indicatorDataMapper.selectAll(queryEscalation);
        //todo 分页插件超过最后一页了，结果还是会默认查询最后一页，先暂时这样 这里是分页插件的问题，后续有空看怎么改合适
        List<IndicatorDataEntity> count = indicatorDataMapper.selectAll(queryEscalation);
        if (count.size() <  (queryEscalation.getPageSize() * queryEscalation.getPageNumber())) {
            return null;
        }
        //把list里面的ids全部单拎出来，去重，然后查询把所有的元素id查出来 但是还是要分月表，天表，手填表 所以数据源list应该分类，暂时只考虑天表
        List<String> elementIds = new ArrayList<>();
        for (IndicatorDataEntity indicatorDataEntity : list) {
            if (StringUtils.isNotBlank(indicatorDataEntity.getIds())) {
                String[] split = indicatorDataEntity.getIds().split(",");
                elementIds.addAll(Arrays.asList(split));
            }
        }
        if (elementIds.isEmpty()) {
            return null;
        }
        elementIds = elementIds.stream().distinct().collect(Collectors.toList());
        //查询元素定义表，确定元素数据来源
        List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
        //分别得出天表，月表，手填表的元素数据
        List<ElementDataEntity> dayTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "1".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> monthTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "2".equals(s.getDataTable())).collect(Collectors.toList());
        List<ElementDataEntity> handTable = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && "3".equals(s.getDataTable())).collect(Collectors.toList());
        List<DepartmentIndicatorEntity> dayData = new ArrayList<>();
        if (!CollectionUtils.isEmpty(dayTable)) {
            queryEscalation.setElementIds(dayTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            dayData = elementDataDayMapper.queryEscalation(queryEscalation); //天表数据
        }
        List<DepartmentIndicatorEntity> monthData = new ArrayList<>();
        if (!CollectionUtils.isEmpty(monthTable)) {
            queryEscalation.setElementIds(dayTable.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            monthData = elementDataMonthMapper.queryEscalation(queryEscalation); //月表数据
        }
        Map<String, List<DepartmentIndicatorEntity>> dayMap = dayData.stream().filter(s -> s.getId() != null).collect(Collectors.groupingBy(DepartmentIndicatorEntity::getId));
        Map<String, List<DepartmentIndicatorEntity>> monthMap = monthData.stream().filter(s -> s.getId() != null).collect(Collectors.groupingBy(DepartmentIndicatorEntity::getId));
        dayMap = null == dayMap ? new HashMap<>() : dayMap;
        monthMap = null == monthMap ? new HashMap<>() : monthMap;
        for (IndicatorDataEntity entity : list) {

            //构建EscalationData对象
            EscalationData escalationData = new EscalationData();
            escalationData.setProject(entity.getIndexCode() + entity.getIndexName());
            escalationData.setUnit(entity.getIndexUnit());
            escalationData.setRow(entity.getRank());
            //todo 如果是手填指标，就要查询手填表 不是手填指标才根据公式计算
            //根据ids求出元素表中的元素，然后代入计算公式中解析
            if (StringUtils.isNotBlank(entity.getIds())) {
                //指标的计算公式
                String calculationFormulaId = entity.getCalculationFormulaId();
                List<DepartmentIndicatorEntity> elementDays = new ArrayList<>();
                String[] ids = entity.getIds().split(",");
                for (String id : ids) {
                    if (!CollectionUtils.isEmpty(dayMap.get(id))) {
                        List<DepartmentIndicatorEntity> mapValues = dayMap.get(id);
                        elementDays.addAll(mapValues);
                    } else if (!CollectionUtils.isEmpty(monthMap.get(id))) {
                        List<DepartmentIndicatorEntity> mapValues = monthMap.get(id);
                        elementDays.addAll(mapValues);
                    }
                }
                //todo 存在一个bug  departmentIndicatorEntities如果不存在当前查询的日期的数据的时候，动态列部分数据就会丢失列
                CalculatorUtils.calculator(elementDays, calculationFormulaId, escalationData, queryEscalation);
            }
            //如果escalationData.getDynamicColumns() 为空或者长度比queryEscalation.size要短，就补上
            if (escalationData.getDynamicColumns().isEmpty() || escalationData.getDynamicColumns().size() < queryEscalation.getTimes().size()) {
                List<String> time = queryEscalation.getTimes();
                for (String s : time) {
                    escalationData.getDynamicColumns().putIfAbsent(s, "-");
                }
            }
            result.add(escalationData);
        }
        return result;
    }

    /**
     * 查询指标下拉列表
     *
     * @return
     */
    public List<DropDownDto> queryIndicators(UserInfo userInfo) {
        return indicatorDataMapper.selectDrop(userInfo);
    }

    public Map<String,List<String>> queryDeptNames() {

        depCPMapper.queryBA();
        return null;
    }


    public List<EscalationDeptData> queryEscalationDeptList(QueryEscalation queryEscalation) {
        //不带科室参数，默认查询页
        if (CollectionUtils.isEmpty(queryEscalation.getDeptNames()) && CollectionUtils.isEmpty(queryEscalation.getElementIds())) {
            //对于全院领导级别 默认就是空查询，需要自己手动筛选查询
            if (queryEscalation.getUserInfo() != null && "JXZB".equals(queryEscalation.getUserInfo().getParentDepartmentId())) {
                //院领导默认查询科室首页，不展示数据，等待自己选择查询条件
                return null;
            } else if (queryEscalation.getUserInfo() != null && "ZNBM".equals(queryEscalation.getUserInfo().getParentDepartmentId())) {
                return null;
            } else {
                //科室的话就没必要了
                queryEscalation.setDeptName(queryEscalation.getUserInfo().getWardName());
                List<IndicatorDataEntity> list = indicatorDataMapper.selectAll(queryEscalation);
                if (CollectionUtils.isEmpty(list)) {
                    return null;
                }
                List<String> elementIds = getAllElementIds(list);
                log.info("查询{}的指标所设计的所有元素:{}", queryEscalation.getUserInfo().getWardName(), elementIds);
                //查询元素定义表，确定元素数据来源
                List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
                Map<String, Map<String, List<DepartmentIndicatorEntity>>> dayMap = getData(elementDataEntities, "1", queryEscalation); //天表数据
                Map<String, Map<String, List<DepartmentIndicatorEntity>>> monthMap = getData(elementDataEntities, "2", queryEscalation); //月表数据
                Map<String, Map<String, List<DepartmentIndicatorEntity>>> handMap = getData(elementDataEntities, "3", queryEscalation); //填报表数据
                List<EscalationDeptData> result = new ArrayList<>();
                String deptName = queryEscalation.getDeptName();
                EscalationDeptData escalationData = new EscalationDeptData();
                escalationData.setProject(deptName);
                escalationData.setRow(1);  //当前科室查询，只会存在一行，n列
                for (IndicatorDataEntity entity : list) {
                    //计算公式
                    String calculationFormulaId = entity.getCalculationFormulaId();
                    if (StringUtils.isBlank(entity.getIds())) {
                        escalationData.getDynamicColumns().put(entity.getIndexName(), "-");
                        continue;
                    }
                    log.info("指标{}的计算公式为:{}",entity.getIndexName(),calculationFormulaId);
                    List<DepartmentIndicatorEntity> elementDays = new ArrayList<>();
                    String[] ids = entity.getIds().split(",");
                    for (String id : ids) {
                        if (!CollectionUtils.isEmpty(dayMap.get(deptName)) && !CollectionUtils.isEmpty(dayMap.get(deptName).get(id))) {
                            List<DepartmentIndicatorEntity> mapValues = dayMap.get(deptName).get(id);
                            elementDays.addAll(mapValues);
                        } else if (!CollectionUtils.isEmpty(monthMap.get(deptName)) && !CollectionUtils.isEmpty(monthMap.get(deptName).get(id))) {
                            List<DepartmentIndicatorEntity> mapValues = monthMap.get(deptName).get(id);
                            elementDays.addAll(mapValues);
                        }else if (!CollectionUtils.isEmpty(handMap.get(deptName)) && !CollectionUtils.isEmpty(handMap.get(deptName).get(id))){
                            List<DepartmentIndicatorEntity> mapValues = handMap.get(deptName).get(id);
                            elementDays.addAll(mapValues);
                        }
                    }
                    log.info("指标{}的元素数据为:{}",entity.getIndexName(),elementDays);
                    CalculatorUtils.calculator(elementDays, entity, calculationFormulaId, escalationData);
                }
                result.add(escalationData);
                return result;
            }
        } else {
            //带条件查询 科室必选
            if(CollectionUtils.isEmpty(queryEscalation.getDeptNames())){
                return null;
            }
            List<String> deptNames = queryEscalation.getDeptNames();
            List<IndicatorDataEntity> list = indicatorDataMapper.selectAll(queryEscalation);
            if (CollectionUtils.isEmpty(list)) {
                return null;
            }
            List<String> elementIds = getAllElementIds(list);
            log.info("查询{}的指标所设计的所有元素:{}", queryEscalation.getUserInfo().getWardName(), elementIds);
            //查询元素定义表，确定元素数据来源
            List<ElementDataEntity> elementDataEntities = elementDataMapper.query(elementIds);
            Map<String, Map<String, List<DepartmentIndicatorEntity>>> dayMap = getData(elementDataEntities, "1", queryEscalation); //天表数据
            Map<String, Map<String, List<DepartmentIndicatorEntity>>> monthMap = getData(elementDataEntities, "2", queryEscalation); //月表数据
            Map<String, Map<String, List<DepartmentIndicatorEntity>>> handMap = getData(elementDataEntities, "3", queryEscalation); //填报表数据
            List<EscalationDeptData> result = new ArrayList<>();
            //一行一行的算
            for (int i = 0; i < deptNames.size(); i++) {
                String deptName = deptNames.get(i);
                EscalationDeptData escalationData = new EscalationDeptData();
                escalationData.setProject(deptName);
                escalationData.setRow(i + 1);
                for (IndicatorDataEntity entity : list) {
                    //计算公式
                    String calculationFormulaId = entity.getCalculationFormulaId();
                    log.info("指标{}的计算公式为:{}",entity.getIndexName(),calculationFormulaId);
                    if (StringUtils.isBlank(entity.getIds())) {
                        escalationData.getDynamicColumns().put(entity.getIndexName(), "-");
                        continue;
                    }
                    List<DepartmentIndicatorEntity> elementDays = new ArrayList<>();
                    String[] ids = entity.getIds().split(",");
                    for (String id : ids) {
                        if (!CollectionUtils.isEmpty(dayMap.get(deptName)) && !CollectionUtils.isEmpty(dayMap.get(deptName).get(id))) {
                            List<DepartmentIndicatorEntity> mapValues = dayMap.get(deptName).get(id);
                            elementDays.addAll(mapValues);
                        } else if (!CollectionUtils.isEmpty(monthMap.get(deptName)) && !CollectionUtils.isEmpty(monthMap.get(deptName).get(id))) {
                            List<DepartmentIndicatorEntity> mapValues = monthMap.get(deptName).get(id);
                            elementDays.addAll(mapValues);
                        }else if (!CollectionUtils.isEmpty(handMap.get(deptName)) && !CollectionUtils.isEmpty(handMap.get(deptName).get(id))){
                            List<DepartmentIndicatorEntity> mapValues = handMap.get(deptName).get(id);
                            elementDays.addAll(mapValues);
                        }
                    }
                    log.info("指标{}的元素数据为:{}",entity.getIndexName(),elementDays);
                    CalculatorUtils.calculator(elementDays, entity, calculationFormulaId, escalationData);
                }
                result.add(escalationData);
            }
            return result;
        }
    }

    /**
     * 导出 部门
     *
     * @param queryEscalation
     * @param response
     */
    public void exportDept(QueryEscalation queryEscalation, HttpServletResponse response) {
        List<EscalationDeptData> escalationData = queryEscalationDeptList(queryEscalation);
        ExcelUtils.exportExcel(response, escalationData, EscalationData.class, queryEscalation);
    }

    /**
     * 查询指标（元素）在总的元素ids
     *
     * @param list
     * @return
     */
    public List<String> getAllElementIds(List<IndicatorDataEntity> list) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        //把list里面的ids全部单拎出来，去重，然后查询把所有的元素id查出来 但是还是要分月表，天表，手填表 所以数据源list应该分类，暂时只考虑天表，月表
        List<String> elementIds = new ArrayList<>();
        for (IndicatorDataEntity indicatorDataEntity : list) {
            if (StringUtils.isNotBlank(indicatorDataEntity.getIds())) {
                String[] split = indicatorDataEntity.getIds().split(",");
                elementIds.addAll(Arrays.asList(split));
            }
        }
        if (elementIds.isEmpty()) {
            return null;
        }
        elementIds = elementIds.stream().distinct().collect(Collectors.toList());
        return elementIds;
    }

    /**
     * 获取对应来源的元素数据
     * @param elementDataEntities
     * @param dataTable 1 元素天表 2元素月表 3填报表
     * @param queryEscalation
     * @return
     */
    public Map<String, Map<String, List<DepartmentIndicatorEntity>>> getData(List<ElementDataEntity> elementDataEntities, String dataTable,QueryEscalation queryEscalation) {
        //分别得出天表，月表，手填表的元素数据
        List<ElementDataEntity> tableData = elementDataEntities.stream().filter(s -> StringUtils.isNotBlank(s.getDataTable()) && dataTable.equals(s.getDataTable())).collect(Collectors.toList());
        List<DepartmentIndicatorEntity> data = new ArrayList<>();
        if (!CollectionUtils.isEmpty(tableData)) {
            queryEscalation.setElementIds(tableData.stream().map(ElementDataEntity::getId).collect(Collectors.toList()));
            if ("1".equals(dataTable)){
                log.info("查询实际数据的元素id为:{}",queryEscalation.getElementIds());
                data = elementDataDayMapper.queryEscalationDept(queryEscalation); //天表数据
            }else if("2".equals(dataTable)){
                data = elementDataMonthMapper.queryEscalationDept(queryEscalation); //月表数据
            }
        }
        //将数据的deptName做成最外层的key，id做成内层的key Map<String,Map<String, List<DepartmentIndicatorEntity>>>
        return data.stream().filter(s->null != s.getDeptName() && null != s.getId())
                .collect(Collectors.groupingBy(DepartmentIndicatorEntity::getDeptName,
                        Collectors.groupingBy(DepartmentIndicatorEntity::getId)));
    }
}